package donajurema.model;

import java.util.ArrayList;
import java.util.Collections;
import org.w3c.dom.*;
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

public class ShopList extends AbstractModelObject
{
	public ArrayList<Shop> m_shops;
	File file;
	static final Boolean AUTO_SAVE = true;
	
	public ArrayList<Shop> getShops()
	{
		return m_shops;
	}
	
	// Constructor
	public ShopList()
	{
		this.m_shops = new ArrayList<Shop>();		// Create new "Shop List"
	}
	
	// Constructor
	public ShopList(String xmlFileName)
	{
		this.m_shops = new ArrayList<Shop>();		// Create new "Shops List"
		this.load(xmlFileName);						// Check if file exists and load Shops
		Collections.sort(m_shops);					// Sort shops in List
	}
	
	// Add new Shop to list, sort and auto-save.
	// Returns the location of the Shop.
	public int addShop(Shop p)
	{
		m_shops.add(p);
		Collections.sort(m_shops);
		int index = m_shops.indexOf(p);
		this.autosave();
		firePropertyChange("Shops", null, m_shops);
		return index;
	}
	
	public void removeShop(Shop p)
	{
		if ((p != null) && (m_shops.contains(p)))
		{
			m_shops.remove(p);
			Collections.sort(m_shops);
			this.autosave();
			firePropertyChange("Shops", null, m_shops);
		}
	}
	
	public void list()
	{
		for (Shop p : m_shops)
		{
			System.out.println(p.toString());
		}
	}

	public void load(String xmlFileName)
	{
		this.file = new File(xmlFileName);				// Create new "file handler"
		if (file.exists())
		{
			this.loadFromXml();
		}
	}

	public void save()
	{
		// Check if file exists
		if (!file.exists())
		{
			try
			{
				file.createNewFile();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		this.saveToXml();
	}
	
	public Shop getShopByName(String name)
	{
		name = name.trim();
		for (Shop p : m_shops)
		{
			if (p.getName().equals(name))
			{
				return p;
			}
		}
		return null;
	}

	private void loadFromXml()
	{
		try
		{
			Document document;
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			document = db.parse(file);
			document.getDocumentElement().normalize();

			NodeList node = document.getElementsByTagName("Shop");

			for (int i = 0; i < node.getLength(); i++)
			{
				Node firstNode = node.item(i);

				if (firstNode.getNodeType() == Node.ELEMENT_NODE)
				{
					Element element = (Element)firstNode;
					
					// Read name from XML
					String name = element.getElementsByTagName("name").item(0).getTextContent();

					// Add Shop with XML data.
					Shop p = new Shop();
					p.setName(name);
					this.addShop(p);
				}
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	private void saveToXml()
	{
		try
		{
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder parser = factory.newDocumentBuilder();
			Document document = parser.newDocument();

			Element root = document.createElement("Shops");

			for (Shop p : m_shops)
			{
				Node newShop = document.createElement("Shop");

				Node newName = document.createElement("name");
				Node nameValue = document.createTextNode(p.getName());
				newName.appendChild(nameValue);

				newShop.appendChild(newName);
				root.appendChild(newShop);
			}
			document.appendChild(root);

			TransformerFactory tFactory = TransformerFactory.newInstance();
			Transformer transformer = tFactory.newTransformer();

			DOMSource source = new DOMSource(document);

			StreamResult result = new StreamResult(file);
			transformer.transform(source, result);
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	private void autosave()
	{
		if (AUTO_SAVE)
		{
			this.save();
		}
	}
}
